/**
 * @Author       : Hejh(3010733382@qq.com)
 * @Version      : V1.0
 * @Date         : 2024-01-16 11:07:00
 * @Description  : 用户-部门接口控制器
 */

const { Op, Transaction } = require('sequelize')
const Mysequelize = require('@/models')
const R = require('@/models/Response')
const { User, UserDepartment, Source } = require('@/models/model')
const { ERROR_USER_CODE } = require('@/constants/errorCode')
const { generatId } = require('@/utils/idUtil')
const { delModel } = require('@/utils/controllerCommon')
const { genSalt, MD5 } = require('@/utils/md5')
const { createUserRootFolder } = require('./userController')
const { getNewPwd } = require('@/utils/common')

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 用于添加或者更新用户-部门记录
 * @param {*} departments 部门列表
 * @param {*} userId 用户ID
 * @param {*} t 事务对象
 * @param {*} isCreate 是否创建
 */
const updateUserDep = async (departments, userId, t, isCreate = false) => {
  if (isCreate) {
    const t2 = await Mysequelize.transaction({
      isolationLevel: Transaction.ISOLATION_LEVELS.READ_UNCOMMITTED
    })
    for (let i = 0; i < departments.length; i++) {
      // 根据userID和departmentID判断记录是否存在
      const dep = departments[i]
      const id = generatId()
      const sort = await UserDepartment.max('sort', { transaction: t2 })
      await UserDepartment.create(
        {
          id,
          userId,
          departmentId: dep.departmentId,
          roleId: dep.roleId,
          sizeMax: dep.sizeMax,
          sort: sort + 1,
          createUser: userId,
          updateUser: userId
        },
        {
          transaction: t
        }
      )
    }
    return
  }

  const t2 = await Mysequelize.transaction({
    isolationLevel: Transaction.ISOLATION_LEVELS.READ_UNCOMMITTED
  })
  // 更新时，不存在新增，存在更新(去除原先的，其他全部新增)

  // const depIds=departments.map(item=>item.)
  await UserDepartment.destroy({
    where: {
      userId: BigInt(userId)
    }
  })

  for (let i = 0; i < departments.length; i++) {
    // 根据userID和departmentID判断记录是否存在
    const dep = departments[i]

    const sort = await UserDepartment.max('sort', { transaction: t2 })
    const id = generatId()
    await UserDepartment.create(
      {
        id,
        userId,
        departmentId: dep.departmentId,
        roleId: dep.roleId,
        sizeMax: dep.sizeMax,
        sort: sort + 1,
        createUser: userId,
        updateUser: userId
      },
      {
        transaction: t
      }
    )
  }
}

const addToDepUpdate = async (departments, userId, t) => {
  const t2 = await Mysequelize.transaction({
    isolationLevel: Transaction.ISOLATION_LEVELS.READ_UNCOMMITTED
  })
  for (let i = 0; i < departments.length; i++) {
    // 根据userID和departmentID判断记录是否存在
    const dep = departments[i]
    const one = await UserDepartment.findOne({
      where: {
        userId: BigInt(userId),
        departmentId: BigInt(dep.departmentId)
      }
    })
    if (!one) {
      const sort = await UserDepartment.max('sort', { transaction: t2 })
      const id = generatId()
      await UserDepartment.create(
        {
          id,
          userId,
          departmentId: dep.departmentId,
          roleId: dep.roleId,
          sizeMax: dep.sizeMax,
          sort: sort + 1,
          createUser: userId,
          updateUser: userId
        },
        {
          transaction: t
        }
      )
      continue
    }
    // 否则更新one记录
    await UserDepartment.update(
      {
        roleId: dep.roleId,
        sizeMax: dep.sizeMax
      },
      {
        where: {
          id: BigInt(one.id)
        },
        transaction: t
      }
    )
  }
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 部门添加用户接口
 * @param {*} ctx
 */
module.exports.createUserToDep = async (ctx) => {
  const {
    username,
    nickname,
    password,
    sizeMax,
    sex,
    email,
    phone,
    roleId,
    departments
  } = ctx.request.body
  const nextId = generatId()

  const salt = genSalt()
  const newPwd = await MD5(password, salt)

  const userObj = {
    salt,
    id: nextId,
    username,
    password: newPwd,
    roleId,
    createUser: ctx.user.id,
    updateUser: ctx.user.id
  }

  // 部分属性可能传了也可能没传
  nickname && (userObj.nickname = nickname)
  sizeMax && (userObj.sizeMax = sizeMax)
  sex && (userObj.sex = sex)
  email && (userObj.email = email)
  phone && (userObj.phone = phone)

  const t = await Mysequelize.transaction()

  try {
    // 添加用户
    const user = await User.create(userObj, { transaction: t })
    // 处理用户对应在部门得权限
    await updateUserDep(departments, nextId, t, true)

    // 添加用户的同时创建用户文件夹，以及默认创建的文件夹
    await createUserRootFolder(ctx, nextId, username, t)
    await t.commit()
    ctx.logs = {
      user
    }
    ctx.body = R.success()
  } catch (error) {
    console.log(error)
    await t.rollback()
    ctx.body = R.error(ERROR_USER_CODE.CREATE_USER_ERROR)
  }
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 部门更新用户接口
 * @param {*} ctx
 */
module.exports.updateUserToDep = async (ctx) => {
  const {
    userId,
    username,
    nickname,
    password,
    sizeMax,
    sex,
    email,
    phone,
    roleId,
    departments
  } = ctx.request.body

  const userObj = {
    id: userId,
    username,
    roleId,
    createUser: ctx.user.id,
    updateUser: ctx.user.id
  }

  // 部分属性可能传了也可能没传
  if (password) {
    const { salt, newPwd } = await getNewPwd(password)
    userObj.password = newPwd
    userObj.salt = salt
  }
  nickname && (userObj.nickname = nickname)
  sizeMax && (userObj.sizeMax = sizeMax)
  sex && (userObj.sex = sex)
  email && (userObj.email = email)
  phone && (userObj.phone = phone)

  const t = await Mysequelize.transaction()

  try {
    // 添加用户
    const user = await User.update(userObj, {
      where: {
        id: BigInt(userId)
      },
      transaction: t
    })
    // 处理用户对应在部门得权限
    await updateUserDep(departments, userId, t, false)
    await t.commit()
    // ctx.logs = {
    //   user
    // }
    ctx.body = R.success()
  } catch (error) {
    console.log(error)
    await t.rollback()
    ctx.body = R.error(ERROR_USER_CODE.CREATE_USER_ERROR)
  }
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 迁移用户接口
 * @param {*} ctx
 */
module.exports.moveUserToDep = async (ctx) => {
  // 移动的前提：存在当前用户-部门记录，更新用户-部门记录
  const t = await Mysequelize.transaction()
  let { userIds, departmentId, curDepId } = ctx.request.body

  const userDeps = await UserDepartment.findAll({
    where: {
      departmentId: BigInt(curDepId),
      userId: {
        [Op.in]: userIds
      }
    }
  })

  const userDepIds = userDeps.map((item) => BigInt(item.id))
  try {
    await UserDepartment.update(
      {
        departmentId
      },
      {
        where: {
          id: {
            [Op.in]: userDepIds
          }
        },
        transaction: t
      }
    )
    await t.commit()
    ctx.body = R.success()
  } catch {
    await t.rollback()
    ctx.body = R.error(ERROR_USER_CODE.USER_DEP_MOVE_ERROR)
  }
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 添加已存在的用户到其他部门
 * @param {*} ctx
 */
module.exports.copyUserToDep = async (ctx) => {
  const { userIds, departments } = ctx.request.body

  const t = await Mysequelize.transaction()
  // 添加到其他部门时，可能已经存在用户-部门记录，这时候直接更新
  try {
    for (let i = 0; i < userIds.length; i++) {
      await addToDepUpdate(departments, userIds[i], t)
    }
    await t.commit()
    ctx.body = R.success()
  } catch (error) {
    await t.rollback()
    ctx.body = R.error(ERROR_USER_CODE.USER_DEP_COPY_ERROR)
  }
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 从部门移除成员
 * @param {*} ctx
 */
module.exports.delUserDeps = async (ctx) => {
  await delModel(
    UserDepartment,
    ERROR_USER_CODE.USER_DEP_REMOVE_ERROR,
    'userDepIds'
  )(ctx)
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 批量设置部门内成员空间大小
 * @param {*} ctx
 */
module.exports.setUserDepsSizeMax = async (ctx) => {
  const { userIds, sizeMax, curDepId } = ctx.request.body

  const userDeps = await UserDepartment.findAll({
    where: {
      departmentId: BigInt(curDepId),
      userId: {
        [Op.in]: userIds
      }
    }
  })

  const userDepIds = userDeps.map((item) => BigInt(item.id))
  const t = await Mysequelize.transaction()
  try {
    await UserDepartment.update(
      {
        sizeMax
      },
      {
        where: {
          id: {
            [Op.in]: userDepIds
          }
        },
        transaction: t
      }
    )
    await t.commit()
    ctx.body = R.success()
  } catch (error) {
    await t.rollback()
    ctx.body = R.error(ERROR_USER_CODE.USER_DEP_SET_SIZEMAX_ERROR)
  }
}
